<template>
	<view id="rune_runewords">
		<clx-dialog :isShow="dialog.show" @dialogConfirm='removeConfirm' @dialogCancel='removeCancel'
			:content="dialog.content"></clx-dialog>
		<HM-filterDropdown :filterData="filterData" :defaultSelected="defaultSelected" @confirm="filterConfirm"
			:updateMenuName="true" :menuTop="menuTop"></HM-filterDropdown>

		<!--  is-disabled -->
		<view v-if="showFrom===$cst_.SHOW_FROM.P1" @tap.stop="onAddClick" class="add_btn_box" hover-class="hover">
			<image src="../../static/img/icons/add.png" mode="aspectFit"></image>

			<!-- <svg-icon-add width="80%" height="80%" :iconColor="'rgba(0, 255, 255, 0.8)'"></svg-icon-add> -->
			<!-- <Icons name="text" color="rgba(0, 255, 255, 0.8)" width="80%" height="80%"></Icons> -->
			<!-- <Icons name="add" color="rgba(0, 255, 255, 0.8)" width="80%" height="80%"></Icons> -->
			<!-- <svg-icon-add width="80%" height="80%" :iconColor="'rgba(0, 255, 255, 0.8)'"></svg-icon-add> -->
		</view>
		<!-- <scroll-view scroll-y="true"> -->
		<view class="no_scroll_view">

			<view class="list_wrapper">
				<!-- $cst_.SHOW_FROM.P1 start -->
				<template v-if="showFrom===$cst_.SHOW_FROM.P1">

					<!-- showData.length > 0 start -->
					<template v-if="showData.length">

						<!-- list start -->
						<view class="list">

							<!-- SHOW_DATA_TYPE.T1 start -->
							<template v-if="showDataType == SHOW_DATA_TYPE.T1">



								<template v-for="data in showData">
									<ContextualMenu
										:item-list="data.can_del?[{data,op:$t('global.button.set')}, {data,op:$t('global.button.del')}]:[{data,op:$t('global.button.set')}]"
										:key="'rw1'+data.order" @item-click="onMenuItemClick" @close="onMenuClose">
										<view class="runeword">
											<view class="runeword_name font">{{data.name || '???'}}</view>
											<view class="effect font">{{data.effect || '...'}}</view>
											<view class="runes_box">
												<template v-for="rune in data.runes_">
													<view :class="['wrapper',rune.lackOrHave]"
														:key="'rune'+ rune.order">
														<view class="img_box">
															<image :src="'/static/img' + rune.src" mode="aspectFit">
															</image>
														</view>
														<view class="name font">{{rune.name}}</view>
													</view>
												</template>
											</view>
										</view>

									</ContextualMenu>
								</template>




							</template>
							<!-- SHOW_DATA_TYPE.T1 end -->


							<!-- SHOW_DATA_TYPE.T2 start -->
							<template v-else>

								<template v-for="data in showData">
									<ContextualMenu
										:item-list="currSelected[0] === CLASSIFY_TYPE.EXCLUSION ? [{data,op:$t('rune.runewords.button.c2possible')}] : [{data,op:$t('rune.runewords.button.c2exclusion')}]"
										:key="'rw2'+data.order" @item-click="onMenuItemClick2" @close="onMenuClose">
										<view class="runeword unknow">
											<view class="runeword_name font">???</view>
											<view class="runes_box">
												<template v-for="rune in data.runes_">
													<view :class="['wrapper',rune.lackOrHave]">
														<view class="img_box">
															<image :src="'/static/img' + rune.src" mode="aspectFit">
															</image>
														</view>
														<view class="name font">{{rune.name}}</view>
													</view>
												</template>
											</view>
										</view>

									</ContextualMenu>
								</template>

							</template>
							<!-- SHOW_DATA_TYPE.T2 end -->


						</view>
						<!-- list end -->

					</template>
					<!-- showData.length > 0 end -->

					<!-- showData.length == 0 start -->
					<template v-else>
						<view class="empty">{{$t('global.empty')}}</view>
					</template>
					<!-- showData.length == 0 end -->
				</template>
				<!-- $cst_.SHOW_FROM.P1 end -->


				<!-- $cst_.SHOW_FROM.P2 start -->
				<template v-if="showFrom===$cst_.SHOW_FROM.P2">
					<!-- list start -->
					<view class="list">

						<template v-if="showDataType == SHOW_DATA_TYPE.T1">
							<template v-for="data in showData">
								<view class="runeword" :key="'rw1'+data.order">
									<view class="runeword_name font">{{data.name || '???'}}</view>
									<view class="effect font">{{data.effect || '...'}}</view>
									<view class="runes_box">
										<template v-for="rune in data.runes_">
											<view class="wrapper" :key="'rune'+ rune.order">
												<view class="img_box">
													<image :src="'/static/img' + rune.src" mode="aspectFit"></image>
												</view>
												<view class="name font">{{rune.name}}</view>
											</view>
										</template>
									</view>
								</view>
							</template>
						</template>



						<template v-else>
							<template v-for="data in showData">
								<view class="runeword unknow" :key="'rw2'+data.order">
									<view class="runeword_name font">???</view>
									<view class="runes_box">
										<template v-for="rune in data.runes_">
											<view class="wrapper">
												<view class="img_box">
													<image :src="'/static/img' + rune.src" mode="aspectFit"></image>
												</view>
												<view class="name font">{{rune.name}}</view>
											</view>
										</template>
									</view>
								</view>
							</template>
						</template>



					</view>
					<!-- list end -->
				</template>
				<!-- $cst_.SHOW_FROM.P2 end -->

			</view>

		</view>
		<!-- </scroll-view> -->
	</view>
</template>


<script>
	/**
	 * @typedef {Object} RuneWord
	 * @property {number} order 序号
	 * @property {string} name 名称
	 * @property {string[]} runes 组合需要的符石名称
	 * @property {string} effect 组合效果
	 * @property {string} effect_r 跟effect一致，数值被替换成占位符@v，可以通过正则使用
	 * @property {number[]} vars 占位符对应数值
	 * @property {boolean} known 是否已知
	 * @property {boolean} unlock 是否发现
	 */

	/**
	 * @typedef {Object} Rune
	 * @property {number} order rune序号
	 * @property {string} name rune名称
	 * @property {string} src rune图片存储位置
	 * @property {number} effect rune等级，不考虑5级以下
	 * @property {string} effect_r 跟effect一致，数值被替换成占位符@v，可以通过正则使用
	 *
	 * @property {number[]} vars 占位符对应数值
	 * @property {boolean} unlock 是否发现
	 *
	 *
	 *
	 */

	/**
	 * @todo 查询大数据后，view高度被撑起来了，影响滚动
	 * @todo 打开选择操作菜单后，禁止滚动
	 * 
	 * HM-filterDropdown https://ext.dcloud.net.cn/plugin?id=1078
	 * 			给里面的两个按钮(重置，确定)文字国际化
	 * 				$t("global.button.reset") $t("global.button.sure")
	 * ContextualMenu  https://ext.dcloud.net.cn/plugin?id=12851
	 * 			我修改里面的contextual-menu/index.vue ，点击菜单项时能拿到数据
	 * clx-dialog https://ext.dcloud.net.cn/plugin?id=1146
	 * */
	import RUNEWORDS_DATA from "@/data/runewords.js";
	import RUNES_DATA from "@/data/runes.js";

	import SvgIconAdd from "@/components/svg/IconAdd.vue";

	import ContextualMenu from "@/components/contextual-menu/index.vue";

	import '@/components/svg/IconText.js';
	import '@/components/svg/IconAdd.js';

	import $utils_ from '@/utils/common.js';
	import $cst_ from '@/utils/constant.js';

	/**
	 * @enum {number}
	 * */
	const SHOW_DATA_TYPE = {
		T1: 1,
		T2: 2,
	};

	/**
	 * @enum {number}
	 * */
	const CLASSIFY_TYPE = {
		ALL: 1,
		UNLOCKED: 2,
		LOCKED: 3,
		POSSIBLE: 4,
		EXCLUSION: 5,
	};

	export default {
		name: 'c-runewords',
		components: {
			SvgIconAdd,
			ContextualMenu,
		},
		props: {
			showFrom: {
				type: Number,
				default: $cst_.SHOW_FROM.P1
			}
		},
		data() {
			return {

				CLASSIFY_TYPE,
				dialog: {
					title: this.$t('global.note.confirmDialog'),
					show: false,
					content: this.$t('global.note.deleteConfirm')
				}, // 删除操作提示框
				delOrder: -1,

				SHOW_DATA_TYPE,

				menuTop: 68 + 6, // tab height + line height
				filterData: [{
					"name": this.$t('rune.runewords.dropdown.class.name'),
					"type": "hierarchy", //字符串类型 必填项 可取值 hierarchy/hierarchy-column/filter/radio  hierarchy/hierarchy-column单或多层级菜单(最多三级); filter筛选多选菜单; radio筛选单选菜单
					"submenu": [{
							"name": this.$t('rune.runewords.dropdown.class.all.name'),
							"value": "c_default",
							"submenu": []
						},
						{
							"name": this.$t('rune.runewords.dropdown.class.unlocked.name'),
							"value": "c_unlocked",
							"submenu": []
						},
						{
							"name": this.$t('rune.runewords.dropdown.class.locked.name'),
							"value": "c_locked",
							"submenu": []
						},
						{
							"name": this.$t('rune.runewords.dropdown.class.possible.name'),
							"value": "c_possible",
							"submenu": []
						},
						{
							"name": this.$t('rune.runewords.dropdown.class.exclusion.name'),
							"value": "c_exclusion",
							"submenu": []
						}
					]
				}, {
					"name": this.$t('rune.runewords.dropdown.filter.name'),
					"type": "filter",
					"submenu": [{
							"name": this.$t('rune.runewords.dropdown.filter.num_of_slots.name'),
							"value": "f1",
							"type": "radio",
							"submenu": [{
								"name": this.$t('rune.runewords.dropdown.filter.num_of_slots.t_slots.name'),
								"value": 2,
								"submenu": []
							}, {
								"name": this.$t('rune.runewords.dropdown.filter.num_of_slots.tr_slots.name'),
								"value": 3,
								"submenu": []
							}]
						},
						{
							"name": this.$t('rune.runewords.dropdown.filter.runes.name'),
							"value": "f2",
							"submenu": []
						}
					]
				}],
				defaultSelected: [],
				currSelected: [undefined, {
					slots: [2, 3],
					runes_exact: false, // 是否按符石名称精确匹配
					runes_o: [],
				}],
				pageSize: 30,
				currPage: 1,


				/** @constant*/
				default_runewords: RUNEWORDS_DATA,

				default_rws_data: [], // 默认runewords数据<依据default_runewords加工过了>
				// user_runewords: [],
				/** @constant*/
				runes: RUNES_DATA,
				/** @constant @description 按英文字母顺序重排runes*/
				runes_sort_char: [],

				/**@type {Map<string, Rune>} */
				runesMap: new Map(),
				/**@type {Map<string, Rune>} */
				runewordsMap: new Map(),
				/**@type {{...RuneWord, runes_: Rune, runes_o: number[]}[]} */

				showDataType: SHOW_DATA_TYPE.T1,

				allCombs: [], // 所有的组合方式
				combsCalced: false, // 计算完

				// 展示的数据
				showData: [],

				bag_runes: [],
			}
		},
		filters: {},
		created() {
			const _this = this;

			let iStatusBarHeight = uni.getSystemInfoSync().statusBarHeight; // 状态栏高度
			// console.log("status bar height", iStatusBarHeight);

			let iStatusBarHeight_rpx = iStatusBarHeight / (uni.upx2px(100) / 100); // px -> rpx
			if (_this.showFrom === $cst_.SHOW_FROM.P1) {
				_this.menuTop = 68 + 6 + iStatusBarHeight_rpx; // tab height + line height + statusbar height
			} else {
				_this.menuTop = iStatusBarHeight_rpx; // statusbar height
			}
			// console.log("menuTop", _this.menuTop);

			/**@link https://www.cnblogs.com/huqi92/p/10102359.html*/
			_this.runes_sort_char = [..._this.runes].sort(function(a, b) {
				return a.name.localeCompare(b.name);
			}); // 按英文字母顺序排序

			// filter->rune 子菜单数
			// 第一个放精确匹配开关
			let filter_subm_data = [{
				"name": this.$t('rune.runewords.dropdown.filter.runes.exact.name'),
				"value": "exact",
				"submenu": [],
			}];
			_this.runes_sort_char.forEach((val) => {
				let obj = {
					"name": val.name,
					"value": val.name,
					"submenu": [],
				};
				filter_subm_data.push(obj);
			});
			_this.$set(_this.filterData[1].submenu[1], "submenu", filter_subm_data);

			// console.log(_this.filterData[1].submenu[1].submenu);

			_this.$nextTick(() => {
				// let arr = _this.runes.map((el, index) => index);
				_this.defaultSelected = [
					[0],
					[
						[0, 1],
						// [...arr]
						[]
					]
				];
			});

			_this.runes.forEach((val) => {
				this.runesMap.set(val.name, val);
			});

			if (_this.showFrom === $cst_.SHOW_FROM.P2) {
				_this.bag_runes = _this.getUserBagRunes();
			}

			_this.getUserRunewords();


			_this.getData(CLASSIFY_TYPE.ALL, _this.currSelected[1]);


			uni.$on("refresh", _this.refresh);
		},
		methods: {
			/**
			 * @description 刷新数据，在添加，修改，删除操作后执行.
			 * */
			refresh() {
				const _this = this;
				console.log("refresh...");
				_this.getData(_this.currSelected[0], _this.currSelected[1], true);
			},
			// 添加按钮点击事件
			onAddClick: $utils_.debounce(function(el) {
				// console.log(el, this);
				const _this = this;
				uni.navigateTo({
					url: `editRunewords`,
					success(res) {
						console.log('跳转到表单页');
						// uni.$emit("test", {
						// 	a: 1,
						// 	b: 2
						// });
						// 通过eventChannel向被打开页面传送数据
						res.eventChannel.emit('acceptDataFromOpenerPage', {
							type: _this.$cst_.OPS.ADD
						});
					}
				});
			}, 500, true),
			// 修改、删除操作
			onMenuItemClick(index, item, close) {
				// console.log(index, item);
				const _this = this;
				if (index === 0) {
					// 修改数据
					uni.navigateTo({
						url: `editRunewords`,
						success(res) {
							console.log('跳转到表单页');
							// uni.$emit("test", {
							// 	a: 1,
							// 	b: 2
							// });
							// 通过eventChannel向被打开页面传送数据
							res.eventChannel.emit('acceptDataFromOpenerPage', {
								type: _this.$cst_.OPS.SET,
								data: item.data
							});
						}
					});
					close();
				} else if (index === 1) {
					// 删除数据
					_this.dialog.show = true;
					_this.delOrder = item.data.order;
					close();
				}
			},
			// 修改exclusion和possible
			onMenuItemClick2(index, item, close) {
				// console.log(index, item);
				const _this = this;
				try {

					let exclusion = _this.getExclusion();
					if (_this.currSelected[0] === CLASSIFY_TYPE.EXCLUSION) {
						console.log("转成possible", item.data);
						// 本质上就是 del exclusion

						let i_ = exclusion.findIndex(el => el.runes_o.toString() === item.data.runes_o.toString());
						if (i_ === -1) {
							throw new Error("删除exclusion异常，未找到正在删除的数据:" + $utils_.JSONStringify(item.data));
						}
						exclusion.splice(i_, 1);


						uni.setStorageSync(_this.$cst_.KEY_EXCLUSION_OF_RUNEWORDS, $utils_.JSONStringify(exclusion));

						_this.refresh();
						uni.showToast({
							title: _this.$t('global.note.op_success'),
							image: '/static/img/toast/success.png',
							duration: 1000
						});

					} else {
						console.log("转成exclusion", item.data);
						// 本质上就是 add exclusion

						let runes = item.data.runes_.map(el => el.order);
						let obj = {
							runes: runes,
							runes_o: [...item.data.runes_o]
						};
						exclusion.push(obj);
						uni.setStorageSync(_this.$cst_.KEY_EXCLUSION_OF_RUNEWORDS, $utils_.JSONStringify(exclusion));

						_this.refresh();
						uni.showToast({
							title: _this.$t('global.note.op_success'),
							image: '/static/img/toast/success.png',
							duration: 1000
						});
					}

					close();
				} catch (err) {
					console.error("修改exclusion或possible出错", err);
					uni.showToast({
						title: _this.$t('global.note.op_failed'),
						image: '/static/img/toast/failure.png',
						duration: 2000
					});
					close();
				}
			},
			// 关闭长按菜单
			onMenuClose() {
				console.log("close menu");
			},
			closeRemoveDialog() {
				this.dialog.show = false;
				this.delOrder = -1;
			},

			// 取消删除
			removeCancel() {
				this.dialog.show = false;
				this.delOrder = -1;
			},
			// 确认删除
			removeConfirm() {
				const _this = this;
				try {
					if (_this.delOrder === -1) {
						throw new Error("删除异常,拿不到要删除的order")
					}
					let user_runewords = _this.getUserRunewords();

					let i_ = user_runewords.findIndex(el => el.order === _this.delOrder);
					// console.log("index:", i_);
					if (i_ === -1) {
						throw new Error(`删除数据时没找到要删除的数据 order:${_this.delOrder}`);
					}
					user_runewords[i_].del = true;


					uni.setStorageSync(_this.$cst_.KEY_OF_RUNEWORDS,
						_this.$utils_.JSONStringify(user_runewords));


					_this.closeRemoveDialog();
					_this.refresh();
					uni.showToast({
						title: _this.$t('global.note.del_success'),
						image: '/static/img/toast/success.png',
						duration: 1000
					});
				} catch (err) {
					console.error(err);

					_this.closeRemoveDialog();
					_this.refresh();
					uni.showToast({
						title: _this.$t('global.note.del_failed'),
						image: '/static/img/toast/failure.png',
						duration: 2000
					});
				}
			},

			/**
			 * @description 将获取到的用户bag_runes数据加工
			 * @param {Array<{name: string; num: number}>} bagRunes 本地存储的用户数据
			 * @return {Array<{name: string; num: number; rune: import('@/data/runes.js').Rune}>}
			 * @todo 转成全局方法或使用vuex
			 * */
			userBagRunesProcesser(bagRunes) {
				const _this = this;
				let data = [];

				for (let i = 0; i < bagRunes.length; i++) {
					let el = bagRunes[i]
					let obj = {
						...el
					};
					let rune = _this.runesMap.get(el.name);
					if (!rune) {
						console.warn(el.name, " 符石未找到");
						continue;
					}
					obj.rune = rune;
					data.push(obj);
				}

				// console.log(data);

				return data;
			},

			/**
			 * @description  获取userdata : bag_runes
			 * @todo globaldata or vuex
			 * */
			getUserBagRunes() {
				const _this = this;
				try {
					// throw new Error("test");
					let val = uni.getStorageSync($cst_.KEY_OF_BAG_RUNES);

					// console.log("val：", val);
					if (val) {
						let data = $utils_.JSONParse(val);
						let res = _this.userBagRunesProcesser(data);

						return res;

					} else {
						// init
						uni.setStorageSync($cst_.KEY_OF_BAG_RUNES, $utils_.JSONStringify([]));
						console.log("bag_runes init");

						return [];
					}
				} catch (e) {
					console.error(e);
					return [];
				}
			},

			/**
			 * @deprecated 用户存储的runword跟默认的数据类型一致
			 * @todo globaldata or vuex
			 * */
			getDefaultRunwords() {
				const _this = this;
				let data = [];

				_this.default_runewords.forEach((val) => {
					let obj = {
						...val
					};
					if (obj.runes.length) {

						let runes_ = []; // runes_存放rune数据
						let runes_o = []; // runes_存放rune对应order，！！！重新按大小排序
						for (let i = 0; i < val.runes.length; i++) {
							let name = val.runes[i];

							let rune = _this.runesMap.get(name);
							if (rune) {
								runes_.push(rune);
								runes_o.push(rune.order);
							} else {
								console.warn(`未找到name为${name}的rune`);
							}
						}
						runes_o.sort((a, b) => (a - b)); // !!! 重新排序，计算所有组合就是按照runes默认顺序来的
						obj.runes_ = runes_;
						obj.runes_o = runes_o;
					} else {
						obj.runes_ = [];
						obj.runes_o = [];
					}
					data.push(obj);
				});

				// console.log(data);

				/**@type {{...RuneWord, runes_: Rune[], runes_o: number[]}[]} */
				_this.default_rws_data = data;
				return data;
			},
			/**
			 * @description 获取exclusion
			 * @to vuex or globaldata
			 * */
			getExclusion() {
				const _this = this;
				try {
					// throw new Error("test");
					let val = uni.getStorageSync(_this.$cst_.KEY_EXCLUSION_OF_RUNEWORDS);
					// console.log(val);
					if (val) {
						return $utils_.JSONParse(val);

					} else {
						console.log("EXCLUSION init");
						uni.setStorageSync(_this.$cst_.KEY_EXCLUSION_OF_RUNEWORDS, $utils_.JSONStringify([]));
						return [];

						// return [{
						// 	runes: [2, 1, 3],
						// 	runes_o: [1, 2, 3]
						// }, {
						// 	runes: [4, 7, 2],
						// 	runes_o: [2, 4, 7]
						// }];// 测试用
					}
				} catch (e) {
					console.error(e);
					return [];
				}
			},
			/**
			 * @description 将获取到的用户userdata  runewords数据加工
			 * @param {RuneWord[]} userRunewords 本地存储的用户数据
			 * @return {{...RuneWord, runes_: Rune[], runes_o: number[]}[]}
			 * @todo 转成全局方法或使用vuex
			 * */
			userRunewordsProcesser(userRunewords) {
				const _this = this;
				let data = [];

				userRunewords.forEach((val) => {
					if (!val.del) {
						// 删除的数据不显示
						let obj = {
							...val
						};
						if (obj.runes.length) {

							let runes_ = []; // runes_存放rune数据
							let runes_o = []; // runes_存放rune对应order，！！！重新按大小排序
							for (let i = 0; i < val.runes.length; i++) {
								let name = val.runes[i];

								let rune = _this.runesMap.get(name);
								if (rune) {
									// runes_.push(rune);
									// 查数据时，每次会重新查用户runewords, rune为 模糊查询(下拉菜单项filter-runes-exact不选上)时，会为runes_添加属性 lackOrHave,如果是引用关系，在非模糊查询时有问题，所有每次深拷贝一下
									runes_.push({
										...rune,
										lackOrHave: ''
									});
									runes_o.push(rune.order);
								} else {
									console.warn(`未找到name为${name}的rune`);
								}
							}
							runes_o.sort((a, b) => (a - b)); // !!! 重新排序，计算所有组合就是按照runes默认顺序来的
							obj.runes_ = runes_;
							obj.runes_o = runes_o;
						} else {
							obj.runes_ = [];
							obj.runes_o = [];
						}
						data.push(obj);
					}
				});

				// console.log(data);

				/**@type {{...RuneWord, runes_: Rune[], runes_o: number[]}[]} */
				return data;
			},
			// 获取userdata : runewords
			getUserRunewords() {
				const _this = this;
				try {
					// throw new Error("test");
					let val = uni.getStorageSync(_this.$cst_.KEY_OF_RUNEWORDS);

					// console.log("val：", val);
					if (val) {
						let data = $utils_.JSONParse(val);
						let res = _this.userRunewordsProcesser(data);


						res.forEach((val) => {
							if (val.runes_o.length) {
								// _this.runewordsMap.set(val.runes_o.toString(), val);
								// 深拷贝，解决模糊匹配 数据引用造成的异常问题
								_this.runewordsMap.set(val.runes_o.toString(), $utils_.JSONParse($utils_
									.JSONStringify(val)));
							}
						});
						// console.log(_this.runewordsMap);

						return res;

					} else {

						// 初始化 ，在用户主动清除KEY_OF_RUNEWORDS中的数据，或者手机系统清除app数据
						console.log("UserRunewords init");

						let str_data = $utils_.JSONStringify(_this.default_runewords);
						let data = $utils_.JSONParse(str_data)
						let res = _this.userRunewordsProcesser(data);


						res.forEach((val) => {
							if (val.runes_o.length) {
								_this.runewordsMap.set(val.runes_o.toString(), val);
							}
						});


						uni.setStorageSync(_this.$cst_.KEY_OF_RUNEWORDS, str_data);
						return res;
					}
				} catch (e) {
					console.error(e);
					return [];
				}
			},
			// 滚动触底，不能用onReachBottom函数名
			onReachBottom_() {
				// console.log("user_runewords,onReachBottom");
				const _this = this;
				_this.getData(_this.currSelected[0], _this.currSelected[1]);
			},
			filterConfirm({
				value,
				index
			}) {
				console.log(value, index);

				const _this = this;
				let classifyType = parseInt(index[0]) + 1;

				let runes_exact_bool = false;
				let filter = {
					slots: value[1][0].map(el => el),
				};

				let runes_o = [];
				for (let i = 0; i < value[1][1].length; i++) {
					let val = value[1][1][i];
					if (val === "exact") {
						runes_exact_bool = true;
					} else {
						let rune = _this.runesMap.get(val);
						// console.log(val, rune);
						if (rune) {
							runes_o.push(rune.order);
						}
					}
				}
				filter.runes_o = runes_o.sort((a, b) => a - b);
				filter.runes_exact = runes_exact_bool;

				_this.getData(classifyType, filter);
			},
			// scrollview滚动触底
			onScrollToLower() {

			},
			isFilterDiff(f1, f2) {
				const _this = this;
				// console.log(f1, f2);
				let d1, d2, d3;
				if ((f1.slots.length == 2 && f2.slots.length == 0) || (f2.slots.length == 2 && f1.slots.length == 0)) {
					d1 = false;
				} else {
					d1 = $utils_.JSONStringify(f1.slots) !== $utils_.JSONStringify(f2.slots);
					// console.log($utils_.JSONStringify(f1.slots));
					// console.log($utils_.JSONStringify(f2.slots));
				}
				// console.log(d1);
				if ((f1.runes_o.length == _this.runes.length && f2.runes_o.length == 0) || (f2.runes_o.length == _this
						.runes.length && f1.runes_o.length == 0)) {
					d2 = false;
				} else {
					d2 = $utils_.JSONStringify(f1.runes_o) !== $utils_.JSONStringify(f2.runes_o);
					// console.log($utils_.JSONStringify(f1.runes_o));
					// console.log($utils_.JSONStringify(f2.runes_o));
				}

				d3 = f1.runes_exact !== f2.runes_exact;

				// console.log(d1,d2,d3);
				return d1 || d2 || d3;
			},
			// 预处理数据
			preSetData() {

			},

			getData(classify, filter, force = false) {
				console.log("getData: ", classify, filter);
				const _this = this;

				if (!force) {
					if (classify == _this.currSelected[0]) {
						// 未切换分类
						if (_this.isFilterDiff(filter, _this.currSelected[1])) {
							// 改变筛选方式
							console.log("改变筛选方式");
							_this.showData = [];
							_this.currPage = 1;
						} else {
							// 未改变筛选方式
							console.log("未改变筛选方式");
							_this.currPage = _this.currPage + 1;
						}
					} else {
						console.log("切换分类");
						// 切换分类
						_this.showData = [];
						_this.currPage = 1;
						_this.currSelected[0] = classify;
					}



					_this.currSelected[1] = filter;
				} else {
					console.log("强制刷新数据");
					_this.currPage = 1;
					_this.showData = [];
				}
				let res;
				switch (classify) {
					case CLASSIFY_TYPE.ALL: {
						_this.showDataType = SHOW_DATA_TYPE.T1;
						console.log("classify ALL");
						let result = _this.getUserRunewordsByPage(_this.pageSize, _this.currPage, filter);
						console.log(result);
						if (result.data.length == 0) {
							_this.currPage = _this.currPage - 1;
							console.log("无数据");
						} else {
							console.log("加载并显示一页数据");
							_this.showData.splice(_this.showData.length, 0, ...result.data);
							// res = result.data;
						}
					}
					break;

					// usedata: unlock && known == true
					case CLASSIFY_TYPE.UNLOCKED: {
						_this.showDataType = SHOW_DATA_TYPE.T1;
						console.log("classify locked");
						let result = _this.getUnlockedByPage(_this.pageSize, _this.currPage, filter);
						console.log(result);
						if (result.data.length == 0) {
							_this.currPage = _this.currPage - 1;
							console.log("无数据");
						} else {
							console.log("加载并显示一页数据");
							_this.showData.splice(_this.showData.length, 0, ...result.data);
							// res = result.data;
						}
					}
					break;
					case CLASSIFY_TYPE.LOCKED: {
						_this.showDataType = SHOW_DATA_TYPE.T1;
						console.log("classify locked");
						let result = _this.getLockedByPage(_this.pageSize, _this.currPage, filter);
						console.log(result);
						if (result.data.length == 0) {
							_this.currPage = _this.currPage - 1;
							console.log("无数据");
						} else {
							console.log("加载并显示一页数据");
							_this.showData.splice(_this.showData.length, 0, ...result.data);
							// res = result.data;
						}
					}
					break;
					// usedata: known == false
					case CLASSIFY_TYPE.EXCLUSION: {
						_this.showDataType = SHOW_DATA_TYPE.T2;
						console.log("classify exclusion");
						let result = _this.getExclusionByPage(_this.pageSize, _this.currPage, filter);
						console.log(result);
						if (result.data.length == 0) {
							_this.currPage = _this.currPage - 1;
							console.log("无数据");
						} else {
							console.log("加载并显示一页数据");
							_this.showData.splice(_this.showData.length, 0, ...result.data);
							// res = result.data;
						}
					}
					break;
					// all calc combination - (known == true) - usedata:exclusion
					case CLASSIFY_TYPE.POSSIBLE: {
						_this.showDataType = SHOW_DATA_TYPE.T2;
						console.log("classify possible");
						let result = _this.getPossibleByPage(_this.pageSize, _this.currPage, filter);
						console.log(result);
						if (result.data.length == 0) {
							_this.currPage = _this.currPage - 1;
							console.log("无数据");
						} else {
							console.log("加载并显示一页数据");
							_this.showData.splice(_this.showData.length, 0, ...result.data);
							// res = result.data;
						}
					}
					break;
					default:
						// console.log("default");
						break;
				}

				// console.log("showData", _this.showData);
				// _this.showData = res;
			},
			/**
			 * @function
			 * @description
			 * @param {number=}  [pageSize = 30] 每页数据量
			 * @param {number=}  [currPage = 1]  当前页数，页数从1开始
			 * @param {object=}  [filter = {}]  筛选条件
			 * @param {boolean=} [bool = false]  查询下一页时递归控制
			 * 
			 * @return {total: number,data: [],nextPage:[]}
			 * */
			getUserRunewordsByPage(pageSize = 30, currPage = 1, filter = {
				slots: [2, 3],
				runes_exact: false, // 是否开启精确匹配
				runes_o: [],
			}, bool = false) {
				const _this = this;
				let res = {
					nextPage: []
				};
				let allData = _this.getUserRunewords();

				// filterOp
				if (filter.slots.length == 1) {
					allData = allData.filter(val => val.runes.length === filter.slots[0]);
				}
				if (filter.runes_o.length > 0 && filter.runes_o.length < _this.runes.length) {
					if (!filter.runes_exact) { // 模糊匹配
						allData = allData.filter(val => {
							if (val.runes_o.length == 2) {
								// let d1 = filter.runes_o.includes(val.runes_o[0]);
								// let d2 = filter.runes_o.includes(val.runes_o[1]);


								let d1 = false;
								let d2 = false;
								let i = 0;
								// !(d1&&d2) 代表两个都找到了
								while (i < filter.runes_o.length && !(d1 && d2)) {
									let el = filter.runes_o[i];

									// !d1 : 比较优化，找到一个了，那另一个肯定不是它
									if (!d1 && el === val.runes_[0].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d1 = true;

										// !d2 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d2 && el === val.runes_[1].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d2 = true;
									}
									i++;
								}

								// 渲染时用的是runes_,直接给它加个lackOrHave,用于动态控制类（显示缺失，拥有效果）,'lack'缺失样式,'have':拥有高亮		
								val.runes_[0].lackOrHave = d1 ? 'have' : 'lack';
								val.runes_[1].lackOrHave = d2 ? 'have' : 'lack';

								return d1 || d2;
							} else if (val.runes_o.length == 3) {
								// return filter.runes_o.includes(val.runes_o[0]) || filter.runes_o.includes(val.runes_o[1]) || filter.runes_o.includes(val.runes_o[2]);
								// let d1 = filter.runes_o.includes(val.runes_o[0]);
								// let d2 = filter.runes_o.includes(val.runes_o[1]);
								// let d3 = filter.runes_o.includes(val.runes_o[2]);

								let d1 = false;
								let d2 = false;
								let d3 = false;
								let i = 0;
								// !(d1&&d2&& d3) 代表三个都找到了
								while (i < filter.runes_o.length && !(d1 && d2 && d3)) {
									let el = filter.runes_o[i];

									// !d1 : 比较优化，找到一个了，那另一个肯定不是它
									if (!d1 && el === val.runes_[0].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d1 = true;

										// !d2 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d2 && el === val.runes_[1].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d2 = true;

										// !d3 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d3 && el === val.runes_[2].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d3 = true;
									}
									i++;
								}

								// 渲染时用的是runes_,直接给它加个lackOrHave,用于动态控制类（显示缺失，拥有效果）,'lack'缺失样式,'have':拥有高亮
								val.runes_[0].lackOrHave = d1 ? 'have' : 'lack';
								val.runes_[1].lackOrHave = d2 ? 'have' : 'lack';
								val.runes_[2].lackOrHave = d3 ? 'have' : 'lack';

								return d1 || d2 || d3;

							}
						});
					} else { //精确匹配
						allData = allData.filter(val => {
							if (val.runes_o.length == 2) {
								return filter.runes_o.includes(val.runes_o[0]) && filter.runes_o.includes(val
									.runes_o[
										1]);
							} else if (val.runes_o.length == 3) {
								return filter.runes_o.includes(val.runes_o[0]) && filter.runes_o.includes(val
									.runes_o[
										1]) && filter.runes_o.includes(val.runes_o[2]);
							}
						});
					}
				}


				let start = (currPage - 1) * pageSize;
				let end = start + pageSize;
				res.data = allData.slice(start, end);
				if (bool) {
					let res1 = _this.getUserRunewordsByPage(pageSize, currPage + 1, filter, false);
					res.nextPage = res1.data;
				}

				res.total = allData.length;

				return res;
			},
			/**
			 * @function
			 * @description
			 * @param {number=}  [pageSize = 30] 每页数据量
			 * @param {number=}  [currPage = 1]  当前页数，页数从1开始
			 * @param {object=}  [filter = {}]  筛选条件
			 * @param {boolean=} [bool = false]  查询下一页时递归控制
			 * 
			 * @return {total: number,data: [],nextPage:[]}
			 * */
			getLockedByPage(pageSize = 30, currPage = 1, filter = {
				slots: [2, 3],
				runes_exact: false, // 是否开启精确匹配
				runes_o: [],
			}, bool = false) {
				const _this = this;
				let res = {
					nextPage: []
				};
				let allData = _this.getUserRunewords();
				allData = allData.filter(el => !el.unlock && el.known);

				// filterOp
				if (filter.slots.length == 1) {
					allData = allData.filter(val => val.runes.length === filter.slots[0]);
				}
				if (filter.runes_o.length > 0 && filter.runes_o.length < _this.runes.length) {
					if (!filter.runes_exact) { // 模糊匹配
						allData = allData.filter(val => {
							if (val.runes_o.length == 2) {
								// let d1 = filter.runes_o.includes(val.runes_o[0]);
								// let d2 = filter.runes_o.includes(val.runes_o[1]);


								let d1 = false;
								let d2 = false;
								let i = 0;
								// !(d1&&d2) 代表两个都找到了
								while (i < filter.runes_o.length && !(d1 && d2)) {
									let el = filter.runes_o[i];

									// !d1 : 比较优化，找到一个了，那另一个肯定不是它
									if (!d1 && el === val.runes_[0].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d1 = true;

										// !d2 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d2 && el === val.runes_[1].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d2 = true;
									}
									i++;
								}

								// 渲染时用的是runes_,直接给它加个lackOrHave,用于动态控制类（显示缺失，拥有效果）,'lack'缺失样式,'have':拥有高亮
								val.runes_[0].lackOrHave = d1 ? 'have' : 'lack';
								val.runes_[1].lackOrHave = d2 ? 'have' : 'lack';

								return d1 || d2;
							} else if (val.runes_o.length == 3) {
								// return filter.runes_o.includes(val.runes_o[0]) || filter.runes_o.includes(val.runes_o[1]) || filter.runes_o.includes(val.runes_o[2]);
								// let d1 = filter.runes_o.includes(val.runes_o[0]);
								// let d2 = filter.runes_o.includes(val.runes_o[1]);
								// let d3 = filter.runes_o.includes(val.runes_o[2]);

								let d1 = false;
								let d2 = false;
								let d3 = false;
								let i = 0;
								// !(d1 && d2 && d3) 代表三个都找到了
								while (i < filter.runes_o.length && !(d1 && d2 && d3)) {
									let el = filter.runes_o[i];

									// !d1 : 比较优化，找到一个了，那另一个肯定不是它
									if (!d1 && el === val.runes_[0].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d1 = true;

										// !d2 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d2 && el === val.runes_[1].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d2 = true;

										// !d3 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d3 && el === val.runes_[2].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d3 = true;
									}
									i++;
								}

								// 渲染时用的是runes_,直接给它加个lackOrHave,用于动态控制类（显示缺失，拥有效果）,'lack'缺失样式,'have':拥有高亮
								val.runes_[0].lackOrHave = d1 ? 'have' : 'lack';
								val.runes_[1].lackOrHave = d2 ? 'have' : 'lack';
								val.runes_[2].lackOrHave = d3 ? 'have' : 'lack';

								return d1 || d2 || d3;

							}
						});
					} else { //精确匹配
						allData = allData.filter(val => {
							if (val.runes_o.length == 2) {
								return filter.runes_o.includes(val.runes_o[0]) && filter.runes_o.includes(val
									.runes_o[
										1]);
							} else if (val.runes_o.length == 3) {
								return filter.runes_o.includes(val.runes_o[0]) && filter.runes_o.includes(val
									.runes_o[
										1]) && filter.runes_o.includes(val.runes_o[2]);
							}
						});
					}
				}


				let start = (currPage - 1) * pageSize;
				let end = start + pageSize;
				res.data = allData.slice(start, end);
				if (bool) {
					let res1 = _this.getLockedByPage(pageSize, currPage + 1, filter, false);
					res.nextPage = res1.data;
				}

				res.total = allData.length;

				return res;
			},

			/**
			 * @function
			 * @description
			 * @param {number=}  [pageSize = 30] 每页数据量
			 * @param {number=}  [currPage = 1]  当前页数，页数从1开始
			 * @param {object=}  [filter = {}]  筛选条件
			 * @param {boolean=} [bool = false]  查询下一页时递归控制
			 * 
			 * @return {total: number,data: [],nextPage:[]}
			 * */
			getUnlockedByPage(pageSize = 30, currPage = 1, filter = {
				slots: [2, 3],
				runes_exact: false, // 是否开启精确匹配
				runes_o: [],
			}, bool = false) {
				const _this = this;
				let res = {
					nextPage: []
				};
				let allData = _this.getUserRunewords();
				allData = allData.filter(el => el.unlock && el.known);

				// filterOp
				if (filter.slots.length == 1) {
					allData = allData.filter(val => val.runes.length === filter.slots[0]);
				}
				if (filter.runes_o.length > 0 && filter.runes_o.length < _this.runes.length) {
					if (!filter.runes_exact) { // 模糊匹配
						allData = allData.filter(val => {
							if (val.runes_o.length == 2) {
								// let d1 = filter.runes_o.includes(val.runes_o[0]);
								// let d2 = filter.runes_o.includes(val.runes_o[1]);


								let d1 = false;
								let d2 = false;
								let i = 0;
								// !(d1&&d2) 代表两个都找到了
								while (i < filter.runes_o.length && !(d1 && d2)) {
									let el = filter.runes_o[i];

									// !d1 : 比较优化，找到一个了，那另一个肯定不是它
									if (!d1 && el === val.runes_[0].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d1 = true;

										// !d2 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d2 && el === val.runes_[1].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d2 = true;
									}
									i++;
								}

								// 渲染时用的是runes_,直接给它加个lackOrHave,用于动态控制类（显示缺失，拥有效果）,'lack'缺失样式,'have':拥有高亮
								val.runes_[0].lackOrHave = d1 ? 'have' : 'lack';
								val.runes_[1].lackOrHave = d2 ? 'have' : 'lack';

								return d1 || d2;
							} else if (val.runes_o.length == 3) {
								// return filter.runes_o.includes(val.runes_o[0]) || filter.runes_o.includes(val.runes_o[1]) || filter.runes_o.includes(val.runes_o[2]);
								// let d1 = filter.runes_o.includes(val.runes_o[0]);
								// let d2 = filter.runes_o.includes(val.runes_o[1]);
								// let d3 = filter.runes_o.includes(val.runes_o[2]);

								let d1 = false;
								let d2 = false;
								let d3 = false;
								let i = 0;
								// !(d1&&d2&&d3) 代表三个都找到了
								while (i < filter.runes_o.length && !(d1 && d2 && d3)) {
									let el = filter.runes_o[i];

									// !d1 : 比较优化，找到一个了，那另一个肯定不是它
									if (!d1 && el === val.runes_[0].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d1 = true;

										// !d2 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d2 && el === val.runes_[1].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d2 = true;

										// !d3 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d3 && el === val.runes_[2].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d3 = true;
									}
									i++;
								}

								// 渲染时用的是runes_,直接给它加个lackOrHave,用于动态控制类（显示缺失，拥有效果）,'lack'缺失样式,'have':拥有高亮
								val.runes_[0].lackOrHave = d1 ? 'have' : 'lack';
								val.runes_[1].lackOrHave = d2 ? 'have' : 'lack';
								val.runes_[2].lackOrHave = d3 ? 'have' : 'lack';

								return d1 || d2 || d3;

							}
						});
					} else { //精确匹配
						allData = allData.filter(val => {
							if (val.runes_o.length == 2) {
								return filter.runes_o.includes(val.runes_o[0]) && filter.runes_o.includes(val
									.runes_o[
										1]);
							} else if (val.runes_o.length == 3) {
								return filter.runes_o.includes(val.runes_o[0]) && filter.runes_o.includes(val
									.runes_o[
										1]) && filter.runes_o.includes(val.runes_o[2]);
							}
						});
					}
				}


				let start = (currPage - 1) * pageSize;
				let end = start + pageSize;
				res.data = allData.slice(start, end);
				if (bool) {
					let res1 = _this.getUnlockedByPage(pageSize, currPage + 1, filter, false);
					res.nextPage = res1.data;
				}

				res.total = allData.length;

				return res;
			},

			/**
			 * @function
			 * @description 计算所有runes组合方式，修改user_runewords和runes后记得重新计算
			 * */
			calcAllCombs() {
				const _this = this;
				// console.log("calc...");
				let res = [];
				let user_runewords = _this.getUserRunewords();
				let order = user_runewords.length;

				let runes = $utils_.JSONParse($utils_.JSONStringify(_this.runes)); // 深拷贝，解决模糊匹配查询数据引用问题

				// calc all 2 slots combs
				for (let i = 0; i < runes.length - 1; i++) {
					let runeA = runes[i];
					for (let j = i + 1; j < runes.length; j++) {
						let runeB = runes[j];

						// 剔除user_runewords
						let key = runeA.order + "," + runeB.order;
						let rune = this.runewordsMap.get(key);
						if (!rune) {
							order++;
							let obj = {
								order,
								name: "",
								runes: [runeA.name, runeB.name],
								runes_: [runeA, runeB],
								runes_o: [runeA.order, runeB.order],
								effect: "",
								effect_r: "",
								vars: [],
								known: false,
								unlock: false,
							};
							res.push(obj);
						} else {
							// console.log(`剔除${key}`);
						}
					}
				}
				// console.log("all slot2 combs:", $utils_.JSONParse($utils_.JSONStringify(res)));

				// calc all 3 slots combs
				for (let i = 0; i < runes.length - 2; i++) {
					let runeA = runes[i];
					for (let j = i + 1; j < runes.length - 1; j++) {
						let runeB = runes[j];
						for (let k = j + 1; k < runes.length; k++) {
							let runeC = runes[k];

							// 剔除user_runewords
							let key = runeA.order + "," + runeB.order + "," + runeC.order;
							let rune = this.runewordsMap.get(key);

							if (!rune) {
								order++;
								let obj = {
									order,
									name: "",
									runes: [runeA.name, runeB.name, runeC.name],
									runes_: [runeA, runeB, runeC],
									runes_o: [runeA.order, runeB.order, runeC.order],
									effect: "",
									effect_r: "",
									vars: [],
									known: false,
									unlock: false,
								};
								res.push(obj);
							} else {
								// console.log(`剔除${key}`);
							}
						}
					}
				}
				// console.log("all combs:", $utils_.JSONParse($utils_.JSONStringify(res)));

				_this.allCombs = res;

				/**@deprecated*/
				_this.combsCalced = true;
			},
			getAllPossible() {
				// console.log("getAllPossible...");
				const _this = this;

				/**@deprecated @description 原本是为了计算优化的，不过后面加了runewords编辑功能，要考虑重新计算的；不过简单粗暴的方法就每次重新计算；而且如果真想优化复用它的话，还要考虑模糊匹配的用的数据引用问题*/
				// if (!_this.combsCalced) {
				// 	_this.calcAllCombs();
				// }

				_this.calcAllCombs();
				/**
				 * [{runes:[2,1,3],runes_o: [1,2,3]},{runes,runes_o}]
				 * */
				// 剔除EXCLUSION
				let exclusion = _this.getExclusion();
				// console.log(460, exclusion);
				if (exclusion.length) {
					let arr = [];
					for (let i = 0; i < _this.allCombs.length; i++) {
						let comb = _this.allCombs[i];

						let index = exclusion.findIndex(ele => {
							let str1 = ele.runes_o.toString();
							let str2 = comb.runes_o.toString();
							return str1 == str2;
						});

						if (index === -1) {
							arr.push(comb);
						} else {
							// console.log(index);
						}
					}

					_this.allCombs = arr;
				}
				return _this.allCombs;
			},

			/**
			 * @function
			 * @description
			 * @param {number=}  [pageSize = 30] 每页数据量
			 * @param {number=}  [currPage = 1]  当前页数，页数从1开始
			 * @param {object=}  [filter = {}]  筛选条件
			 * @param {boolean=} [bool = false]  查询下一页时递归控制
			 * 
			 * @return {total: number,data: [],nextPage:[]}
			 * */
			getPossibleByPage(pageSize = 30, currPage = 1, filter = {
				slots: [2, 3],
				runes_exact: false, // 是否开启精确匹配
				runes_o: [],
			}, bool = false) {
				const _this = this;
				let res = {
					nextPage: []
				};
				let allData = _this.getAllPossible();

				// filterOp
				if (filter.slots.length == 1) {
					allData = allData.filter(val => val.runes.length === filter.slots[0]);
				}
				if (filter.runes_o.length > 0 && filter.runes_o.length < _this.runes.length) {
					if (!filter.runes_exact) { // 模糊匹配
						allData = allData.filter(val => {
							if (val.runes_o.length == 2) {
								// let d1 = filter.runes_o.includes(val.runes_o[0]);
								// let d2 = filter.runes_o.includes(val.runes_o[1]);


								let d1 = false;
								let d2 = false;
								let i = 0;
								// !(d1&&d2) 代表两个都找到了
								while (i < filter.runes_o.length && !(d1 && d2)) {
									let el = filter.runes_o[i];

									// !d1 : 比较优化，找到一个了，那另一个肯定不是它
									if (!d1 && el === val.runes_[0].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d1 = true;

										// !d2 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d2 && el === val.runes_[1].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d2 = true;
									}
									i++;
								}

								// 渲染时用的是runes_,直接给它加个lackOrHave,用于动态控制类（显示缺失，拥有效果）,'lack'缺失样式,'have':拥有高亮
								val.runes_[0].lackOrHave = d1 ? 'have' : 'lack';
								val.runes_[1].lackOrHave = d2 ? 'have' : 'lack';

								return d1 || d2;
							} else if (val.runes_o.length == 3) {
								// return filter.runes_o.includes(val.runes_o[0]) || filter.runes_o.includes(val.runes_o[1]) || filter.runes_o.includes(val.runes_o[2]);
								// let d1 = filter.runes_o.includes(val.runes_o[0]);
								// let d2 = filter.runes_o.includes(val.runes_o[1]);
								// let d3 = filter.runes_o.includes(val.runes_o[2]);

								let d1 = false;
								let d2 = false;
								let d3 = false;
								let i = 0;
								// !(d1&&d2&&d3) 代表三个都找到了
								while (i < filter.runes_o.length && !(d1 && d2 && d3)) {
									let el = filter.runes_o[i];

									// !d1 : 比较优化，找到一个了，那另一个肯定不是它
									if (!d1 && el === val.runes_[0].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d1 = true;

										// !d2 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d2 && el === val.runes_[1].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d2 = true;

										// !d3 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d3 && el === val.runes_[2].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d3 = true;
									}
									i++;
								}

								// 渲染时用的是runes_,直接给它加个lackOrHave,用于动态控制类（显示缺失，拥有效果）,'lack'缺失样式,'have':拥有高亮
								val.runes_[0].lackOrHave = d1 ? 'have' : 'lack';
								val.runes_[1].lackOrHave = d2 ? 'have' : 'lack';
								val.runes_[2].lackOrHave = d3 ? 'have' : 'lack';

								return d1 || d2 || d3;

							}
						});
					} else { //精确匹配
						allData = allData.filter(val => {
							if (val.runes_o.length == 2) {
								return filter.runes_o.includes(val.runes_o[0]) && filter.runes_o.includes(val
									.runes_o[
										1]);
							} else if (val.runes_o.length == 3) {
								return filter.runes_o.includes(val.runes_o[0]) && filter.runes_o.includes(val
									.runes_o[
										1]) && filter.runes_o.includes(val.runes_o[2]);
							}
						});
					}
				}


				let start = (currPage - 1) * pageSize;
				let end = start + pageSize;
				res.data = allData.slice(start, end);
				if (bool) {
					let res1 = _this.getPossibleByPage(pageSize, currPage + 1, filter, false);
					res.nextPage = res1.data;
				}

				res.total = allData.length;

				return res;
			},
			/**
			 * @function
			 * @description
			 * @param {number=}  [pageSize = 30] 每页数据量
			 * @param {number=}  [currPage = 1]  当前页数，页数从1开始
			 * @param {object=}  [filter = {}]  筛选条件
			 * @param {boolean=} [bool = false]  查询下一页时递归控制
			 * 
			 * @return {total: number,data: [],nextPage:[]}
			 * */
			getExclusionByPage(pageSize = 30, currPage = 1, filter = {
				slots: [2, 3],
				runes_exact: false, // 是否开启精确匹配
				runes_o: [],
			}, bool = false) {
				const _this = this;
				let res = {
					nextPage: []
				};
				let exclusion = _this.getExclusion();
				// console.log(exclusion);
				let allData = exclusion.map((el, index) => {
					// console.log(el);
					if (el.runes_o.length == 2) {
						let runeA = _this.runes[el.runes_o[0] - 1];
						let runeB = _this.runes[el.runes_o[1] - 1];
						console.log(runeA, runeB);
						let obj = {
							order: index,
							name: "",
							runes: [runeA.name, runeB.name],
							runes_: [runeA, runeB],
							runes_o: [runeA.order, runeB.order],
							effect: "",
							effect_r: "",
							vars: [],
							known: false,
							unlock: false,
						};
						return obj;
					} else if (el.runes_o.length == 3) {
						let runeA = _this.runes[el.runes_o[0] - 1];
						let runeB = _this.runes[el.runes_o[1] - 1];
						let runeC = _this.runes[el.runes_o[2] - 1];
						// console.log(runeA, runeB, runeC);
						let obj = {
							order: index,
							name: "",
							runes: [runeA.name, runeB.name, runeC.name],
							runes_: [runeA, runeB, runeC],
							runes_o: [runeA.order, runeB.order, runeC.order],
							effect: "",
							effect_r: "",
							vars: [],
							known: false,
							unlock: false,
						};
						return obj;
					}
				});


				// filterOp
				if (filter.slots.length == 1) {
					allData = allData.filter(val => val.runes.length === filter.slots[0]);
				}
				if (filter.runes_o.length > 0 && filter.runes_o.length < _this.runes.length) {
					if (!filter.runes_exact) { // 模糊匹配
						allData = allData.filter(val => {
							if (val.runes_o.length == 2) {
								// let d1 = filter.runes_o.includes(val.runes_o[0]);
								// let d2 = filter.runes_o.includes(val.runes_o[1]);


								let d1 = false;
								let d2 = false;
								let i = 0;
								// !(d1&&d2) 代表两个都找到了
								while (i < filter.runes_o.length && !(d1 && d2)) {
									let el = filter.runes_o[i];

									// !d1 : 比较优化，找到一个了，那另一个肯定不是它
									if (!d1 && el === val.runes_[0].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d1 = true;

										// !d2 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d2 && el === val.runes_[1].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d2 = true;
									}
									i++;
								}

								// 渲染时用的是runes_,直接给它加个lackOrHave,用于动态控制类（显示缺失，拥有效果）,'lack'缺失样式,'have':拥有高亮
								val.runes_[0].lackOrHave = d1 ? 'have' : 'lack';
								val.runes_[1].lackOrHave = d2 ? 'have' : 'lack';

								return d1 || d2;
							} else if (val.runes_o.length == 3) {
								// return filter.runes_o.includes(val.runes_o[0]) || filter.runes_o.includes(val.runes_o[1]) || filter.runes_o.includes(val.runes_o[2]);
								// let d1 = filter.runes_o.includes(val.runes_o[0]);
								// let d2 = filter.runes_o.includes(val.runes_o[1]);
								// let d3 = filter.runes_o.includes(val.runes_o[2]);

								let d1 = false;
								let d2 = false;
								let d3 = false;
								let i = 0;
								// !(d1&&d2&&d3) 代表三个都找到了
								while (i < filter.runes_o.length && !(d1 && d2 && d3)) {
									let el = filter.runes_o[i];

									// !d1 : 比较优化，找到一个了，那另一个肯定不是它
									if (!d1 && el === val.runes_[0].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d1 = true;

										// !d2 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d2 && el === val.runes_[1].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d2 = true;

										// !d3 : 比较优化，找到一个了，那另一个肯定不是它
									} else if (!d3 && el === val.runes_[2].order) {
										// 渲染时用的是runes_，判断变量（d1,d2,d3）跟它一一对应
										d3 = true;
									}
									i++;
								}

								// 渲染时用的是runes_,直接给它加个lackOrHave,用于动态控制类（显示缺失，拥有效果）,'lack'缺失样式,'have':拥有高亮
								val.runes_[0].lackOrHave = d1 ? 'have' : 'lack';
								val.runes_[1].lackOrHave = d2 ? 'have' : 'lack';
								val.runes_[2].lackOrHave = d3 ? 'have' : 'lack';

								return d1 || d2 || d3;

							}
						});
					} else { //精确匹配
						allData = allData.filter(val => {
							if (val.runes_o.length == 2) {
								return filter.runes_o.includes(val.runes_o[0]) && filter.runes_o.includes(val
									.runes_o[
										1]);
							} else if (val.runes_o.length == 3) {
								return filter.runes_o.includes(val.runes_o[0]) && filter.runes_o.includes(val
									.runes_o[
										1]) && filter.runes_o.includes(val.runes_o[2]);
							}
						});
					}
				}

				let start = (currPage - 1) * pageSize;
				let end = start + pageSize;
				res.data = allData.slice(start, end);

				if (bool) {
					let res1 = _this.getExclusionByPage(pageSize, currPage + 1, filter, false);
					res.nextPage = res1.data;
				}

				res.total = allData.length;

				return res;
			},
		},

		mounted() {
			// console.log(this);
		},
		destroyed() {
			this.runesMap.clear();
			this.runewordsMap.clear();


			uni.$off("refresh");
		}
	};
</script>

<style lang="scss" scoped>
	#rune_runewords {
		width: 100%;
		height: 100%;

		background-color: rgb(28, 28, 28);
		position: relative;
		// z-index: 0;


		// padding-top: calc(88rpx + 10rpx);
		padding-top: 88rpx;
		box-sizing: border-box;

		// overflow: scroll;
		.add_btn_box {
			position: fixed;
			top: calc(200rpx + var(--status-bar-height));
			right: 20rpx;
			z-index: 2;
			background-color: rgba(0, 122, 255, 0.8);
			height: 100rpx;
			width: 100rpx;
			border-radius: 50%;
			display: flex;
			align-items: center;
			justify-content: center;

			uni-image {
				width: 80%;
				height: 80%;
			}

			&.hover {
				transform: scale(1.1) !important;
			}

			&.is-disabled {
				background-color: gray;
				transform: none !important;
			}
		}


		// uni-scroll-view {
		.no_scroll_view {
			// margin-bottom: var(–window-bottom);
			background-color: rgb(28, 28, 28);
		}

		.no_scroll_view {
			// height: 100%;
			position: relative;
			// z-index: 0; // 防透视，z-index必须搭配position使用

			// background-color: chocolate;
			.list_wrapper {
				box-sizing: border-box;
				// padding: 10rpx 20rpx 40rpx;
				padding: 20rpx 20rpx calc(var(--window-bottom) + 20rpx);

				.empty {

					text-align: center;
					color: white;
					font-size: 48rpx;
					line-height: 84rpx;
				}
			}

			.list {

				// 内置浏览器无效，安卓真机有效
				// .contextual-menu:has(+ .contextual-menu-mask-show) {
				// 	.runeword {
				// 		background-color: rgba(100, 32, 21, 255);
				// 	}
				// }
				.contextual-menu.mask-show {
					.runeword {
						background-color: rgba(100, 32, 21, 255);
					}
				}

				// display: flex;
				// flex-direction: row;
				// flex-wrap: wrap;

				display: grid;
				grid-gap: 20rpx;
				// grid-template-columns: 50% 50%;
				grid-template-columns: 1fr 1fr;
				// grid-row-gap: 20rpx;
				// grid-column-gap: 20rpx;

				.runeword {
					width: 100%;
					height: 400rpx;
					background-color: rgba(22, 32, 21, 255);
					border-radius: 32rpx;
					position: relative;
					border: 8rpx rgb(59,90,85) solid;
					box-sizing: border-box;

					// display: flex;
					// flex-wrap: wrap;
					// flex-direction: column;
					// justify-content: center;

					&.unknow {
						height: 220rpx;
					}

					.font {
						display: flex;
						flex-direction: column;
						align-items: center;
						justify-content: center;


						text-align: center;
						color: white;
					}

					.runeword_name {
						// margin-top: 20rpx;
						// margin-bottom: 10rpx;
						padding: 20rpx 10rpx 10rpx;
						box-sizing: border-box;
						color: rgb(1, 255, 227);
						font-weight: 600;
						font-size: 36rpx;
						// width: 100%;
					}

					.effect {
						font-size: 28rpx;
						padding: 0 10rpx;
						box-sizing: border-box;
					}

					.runes_box {
						height: 130rpx;
						position: absolute;
						bottom: 4rpx;
						width: 100%;
						padding: 0 20rpx;
						box-sizing: border-box;


						// background-color: yellow;

						display: flex;
						flex-direction: row;
						justify-content: center;


						.wrapper {

							// 缺少效果
							&.lack {
								uni-image {
									background-color: rgb(247, 98, 96);
								}

								.name {
									color: rgb(247, 98, 96);
								}

							}

							// 匹配高亮
							&.have {

								uni-image {
									background-color: yellow;
								}

								.name {
									color: yellow;
								}
							}

							&:first-child {
								margin-left: 0;
							}

							margin-left: 40rpx;

							// background-color: pink;
							.img_box {
								height: 80rpx;
								width: 80rpx;

								uni-image {
									height: 100%;
									width: 100%;
								}
							}

							.name {
								font-size: 38rpx;
							}
						}
					}

					.txt {
						width: calc(100% - 100rpx);
						// flex: 1;
						height: 100%;

						font-size: 28rpx;
					}
				}
			}


		}

	}
</style>